iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 8
0
自我挑戰組

Angular2學習筆記系列 第 8

Angular 2.3 支援 Component Inheritance 學習筆記

  • 分享至 

  • xImage
  •  

謝謝 Angular User Group的Kevin大大提供的寫作素材。

原文請參考:Component Inheritance in Angular 2

我沒有改變範例,只是想邊翻譯邊操作當做學習筆記,如果有覺得不妥的地方,請再通知我一聲。

有了Component Inheritance的支援,我們可以製作元件的核心功能,

透過繼承去改變樣式及小幅調整功能,就能應付客戶的客製化需求。

Component Inheritance

先整理一下要如何使用 Angular 2.3 的元件繼承

  • Metadata(decorators)

    像是@Input()、@Output()這類的metadata

    子元件可以直接使用或是覆寫自父元件定義的metadata

  • Constructor:

    父元件如果有在Constructor注入Service,子元件可以直接繼承使用。

  • Lifecycle hooks:

    父元件的生命週期方法也會被運作到,就算在子元件中沒有特別定義。

  • Componet inheritance 不會覆蓋掉父元件的templates及styles,必須做個別的操作。

Building with Component Inheritance

接下來可以簡單的試用一下Component Inheritance的功能

原文提供的範例是一個pagination的元件。

父元件原本是這樣

繼承之後,希望能改寫成這樣的子元件

因此父元件需要改變以下幾點

  • 使用HyperLink取代Button

  • 把PageCount放在上下頁功能的中間而不是換行

Base Pagenation Component 的程式碼

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'base-pagination',
  template: `
    <button (click)="previousPage()" [disabled]="!hasPrevious()">Previous</button> 
    <button (click)="nextPage()" [disabled]="!hasNext()">Next</button>

    <p>page {{ page }} of {{ pageCount }}</p>
  `
})
export class BasePaginationComponent {
  @Input() 
  pageCount: number;

  @Input()
  page: number;

  @Output()
  pageChanged = new EventEmitter<number>();

  nextPage() {
    this.page ++;
    this.pageChanged.emit(this.page);
  }

  previousPage() {
    this.page --;
    this.pageChanged.emit(this.page);
  }

  hasPrevious(): boolean { return +this.page > 1; }

  hasNext(): boolean { return +this.page < +this.pageCount; }

}

父元件的程式碼有幾個重點

  • 我們接受二個input變數

    • page 用來代表現在頁數

    • pageCount 用來代表全部頁數

  • 當頁數改變時,會emit PageChanged envent

  • 如果 previous 或 next button達到最小或最大頁數則Disable。

實作 Base Pagenation Component 的繼承

// custom-pagination.component.ts

import { Component } from '@angular/core';
import { BasePaginationComponent } from './base-pagination.component';

@Component({
  selector: 'custom-pagination',
  template: `
    <a (click)="previousPage()" [class.disabled]="!hasPrevious()" 
      href="javascript:void(0)">
      ««
    </a> 
    <span>{{ page }} / {{ pageCount }}</span>
    <a (click)="nextPage()" [class.disabled]="!hasNext()"
      href="javascript:void(0)" >
      »»
    </a>
  `
})
export class CustomPaginationComponent extends BasePaginationComponent {
}

子元件的程式碼的重點如下

  • 首先要import BasePaginationComponent

  • 然後使用 extend 繼承 BasePaginationComponent

  • 修改Template,把Button改成Hyperlink

  • 修改Template,把頁數資訊改到上下頁的中間

  • 我們可以reuse所有從父元件繼承下來的inputs、outputs、properties及function

覆寫父元件的properties

在父元件增加二個Input-previousText、nextText,用來標示上一頁/下一頁按鈕的文字,並且在沒有指定文字時給予預設值。

// base-pagination.component.ts

@Component({
  selector: 'base-pagination',
  template: `
    <button (click)="previousPage()" [disabled]="!hasPrevious()">{{ previousText }}</button> 
    <button (click)="nextPage()" [disabled]="!hasNext()">{{ nextText }}</button>

    <p>page {{ page }} of {{ pageCount }}</p>
  `
})
export class BasePaginationComponent {
  ...

  @Input()
  previousText = 'Previous';

  @Input()
  nextText = 'Next';

  ...

}

接下來我們在子元件,覆寫繼承自父元件的Input-previousText、nextText,重新設定初值為符號<<>>

// custom-pagination.component.ts

import { Component, Input } from '@angular/core';
import { BasePaginationComponent } from './base-pagination.component';

@Component({
  selector: 'custom-pagination',
  template: `
    <a (click)="previousPage()" [class.disabled]="!hasPrevious()" 
      href="javascript:void(0)">
      {{ previousText }}
    </a> 
    <span>{{ page }} / {{ pageCount }}</span>
    <a (click)="nextPage()" [class.disabled]="!hasNext()"
      href="javascript:void(0)" >
      {{ nextText }}
    </a>
  `
})
export class CustomPaginationComponent extends BasePaginationComponent {
  @Input()
  previousText = '<<'; // 覆寫預設值

  @Input()
  nextText = '>>'; // 覆寫預設值

  ...
}

在子元件新增新的property

在子元件建立一個父元件沒有的titleproperty

// custom-pagination.component.ts
@Component({
  selector: 'custom-pagination',
  template: `
    <h2>{{ title }}</h2>
    <a (click)="previousPage()" [class.disabled]="!hasPrevious()" 
      href="javascript:void(0)">
      {{ previousText }}
    </a> 
    <span>{{ page }} / {{ pageCount }}</span>
    <a (click)="nextPage()" [class.disabled]="!hasNext()"
      href="javascript:void(0)" >
      {{ nextText }}
    </a>
  `
})
export class CustomPaginationComponent extends BasePaginationComponent {
  @Input()
  title: string; // title input只有子元件才有

  ...
}

完整的程式碼,可以參考原文作者提供的程式碼範例


上一篇
Angular2 實戰番外篇-MEAN Stack (下)
下一篇
Angular2 實戰篇 (三)
系列文
Angular2學習筆記19
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言